//
// Copyright 2020 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Selector '.mdc-*' should only be used in this project.
// stylelint-disable selector-class-pattern --
// Internal styling for Chip MDC component.

@use 'sass:map';
@use 'sass:meta';
@use 'sass:math';
@use 'sass:color';
@use '@material/dom/dom';
@use '@material/density/density';
@use '@material/feature-targeting/feature-targeting';
@use '@material/shape/shape';
@use '@material/ripple/ripple-theme';
@use '@material/rtl/rtl';
@use '@material/theme/theme';
@use '@material/theme/keys';
@use '@material/elevation/elevation-theme';
@use '@material/tokens/resolvers';
@use '@material/theme/state';
@use '@material/theme/theme-color';
@use '@material/typography/typography';

$height: 32px;
$minimum-height: 24px;
$maximum-height: $height;
$density-scale: density.$default-scale;
$density-config: (
  height: (
    default: $height,
    maximum: $maximum-height,
    minimum: $minimum-height,
  ),
);
$radius: math.div($height, 2);
$type-scale: body2;
$container-color: color.mix(
  theme-color.prop-value(on-surface),
  theme-color.prop-value(surface),
  12%
);
$text-label-color: rgba(theme-color.prop-value(on-surface), 0.87);
$icon-color: rgba(theme-color.prop-value(on-surface), 0.87);
$checkmark-color: rgba(theme-color.prop-value(on-surface), 0.87);
$trailing-action-color: rgba(theme-color.prop-value(on-surface), 0.87);
$ripple-color: on-surface;
$checkmark-size: 20px;
$leading-icon-size: 20px;
$trailing-action-size: 18px;
$leading-padding: 12px;
$trailing-padding: 12px;
$avatar-size: 24px;
$avatar-leading-padding: 4px;
$avatar-trailing-padding: 8px;
$graphic-leading-padding: 6px;
$graphic-trailing-padding: 6px;
$trailing-action-leading-padding: 8px;
$trailing-action-trailing-padding: 8px;
$ripple-target: '.mdc-evolution-chip__ripple';
$ripple-target-primary: '.mdc-evolution-chip__ripple--primary';
$ripple-target-trailing: '.mdc-evolution-chip__ripple--trailing';

// Filter chip colors
$filter-selected-container-color: color.mix(
  theme-color.prop-value(on-surface),
  $container-color,
  8%
);

$light-theme: (
  container-elevation: null,
  container-height: null,
  container-shadow-color: null,
  container-shape: null,
  disabled-label-text-color: null,
  disabled-label-text-opacity: null,
  disabled-outline-color: null,
  disabled-outline-opacity: null,
  elevated-container-color: null,
  elevated-container-elevation: null,
  elevated-container-shadow-color: null,
  container-surface-tint-layer-color: null,
  elevated-disabled-container-color: null,
  elevated-disabled-container-elevation: null,
  elevated-disabled-container-opacity: null,
  elevated-focus-container-elevation: null,
  elevated-hover-container-elevation: null,
  elevated-pressed-container-elevation: null,
  elevated-selected-container-color: null,
  elevated-selected-container-elevation: null,
  elevated-unselected-container-color: null,
  flat-container-elevation: null,
  flat-disabled-outline-color: null,
  flat-disabled-outline-opacity: null,
  flat-disabled-selected-container-color: null,
  flat-disabled-selected-container-opacity: null,
  flat-disabled-selected-outline-color: null,
  flat-disabled-selected-outline-opacity: null,
  flat-disabled-unselected-outline-color: null,
  flat-disabled-unselected-outline-opacity: null,
  flat-focus-outline-color: null,
  flat-outline-color: null,
  flat-outline-width: null,
  flat-selected-container-color: null,
  flat-selected-focus-container-elevation: null,
  flat-selected-hover-container-elevation: null,
  flat-selected-outline-color: null,
  flat-selected-outline-width: null,
  flat-selected-pressed-container-elevation: null,
  flat-unselected-focus-container-elevation: null,
  flat-unselected-focus-outline-color: null,
  flat-unselected-hover-container-elevation: null,
  flat-unselected-outline-color: null,
  flat-unselected-outline-width: null,
  flat-unselected-pressed-container-elevation: null,
  focus-label-text-color: null,
  focus-outline-color: null,
  focus-state-layer-color: null,
  focus-state-layer-opacity: null,
  hover-label-text-color: null,
  hover-state-layer-color: null,
  hover-state-layer-opacity: null,
  label-text-color: null,
  label-text-font: null,
  label-text-line-height: null,
  label-text-size: null,
  label-text-tracking: null,
  label-text-weight: null,
  outline-color: null,
  outline-width: null,
  pressed-label-text-color: null,
  pressed-state-layer-color: null,
  pressed-state-layer-opacity: null,
  selected-focus-label-text-color: null,
  selected-focus-state-layer-color: null,
  selected-focus-state-layer-opacity: null,
  selected-hover-label-text-color: null,
  selected-hover-state-layer-color: null,
  selected-hover-state-layer-opacity: null,
  selected-label-text-color: null,
  selected-pressed-label-text-color: null,
  selected-pressed-state-layer-color: null,
  selected-pressed-state-layer-opacity: null,
  unselected-focus-label-text-color: null,
  unselected-focus-state-layer-color: null,
  unselected-focus-state-layer-opacity: null,
  unselected-hover-label-text-color: null,
  unselected-hover-state-layer-color: null,
  unselected-hover-state-layer-opacity: null,
  unselected-label-text-color: null,
  unselected-pressed-label-text-color: null,
  unselected-pressed-state-layer-color: null,
  unselected-pressed-state-layer-opacity: null,
  with-avatar-avatar-shape: null,
  with-avatar-avatar-size: null,
  with-avatar-disabled-avatar-opacity: null,
  with-icon-disabled-icon-color: null,
  with-icon-disabled-icon-opacity: null,
  with-icon-focus-icon-color: null,
  with-icon-hover-icon-color: null,
  with-icon-icon-color: null,
  with-icon-icon-size: null,
  with-icon-pressed-icon-color: null,
  with-icon-selected-focus-icon-color: null,
  with-icon-selected-hover-icon-color: null,
  with-icon-selected-icon-color: null,
  with-icon-selected-pressed-icon-color: null,
  with-icon-unselected-focus-icon-color: null,
  with-icon-unselected-hover-icon-color: null,
  with-icon-unselected-icon-color: null,
  with-icon-unselected-pressed-icon-color: null,
  with-leading-icon-disabled-leading-icon-color: null,
  with-leading-icon-disabled-leading-icon-opacity: null,
  with-leading-icon-focus-leading-icon-color: null,
  with-leading-icon-hover-leading-icon-color: null,
  with-leading-icon-leading-icon-color: null,
  with-leading-icon-leading-icon-size: null,
  with-leading-icon-pressed-leading-icon-color: null,
  with-trailing-icon-disabled-trailing-icon-color: null,
  with-trailing-icon-disabled-trailing-icon-opacity: null,
  with-trailing-icon-focus-trailing-icon-color: null,
  with-trailing-icon-hover-trailing-icon-color: null,
  with-trailing-icon-pressed-trailing-icon-color: null,
  with-trailing-icon-trailing-icon-color: null,
  with-trailing-icon-trailing-icon-size: null,
);
$_custom-property-prefix: 'chip';

// TODO(b/259513131): Move theme resolution to variant theme
// and remove custom property declaration when all customers are ready to be migrated
@mixin theme($theme, $resolvers: resolvers.$material) {
  @include theme.validate-theme($light-theme, $theme);
  $theme: resolve-theme($theme, $resolvers: $resolvers);
  @include keys.declare-custom-properties(
    $theme,
    $prefix: $_custom-property-prefix
  );
}

// TODO(b/259513131): Move theme resolution to variant theme
// and remove custom property declaration when all customers are ready to be migrated
@mixin theme-styles($theme, $resolvers: resolvers.$material) {
  @include theme.validate-theme-styles($light-theme, $theme);
  $theme: resolve-theme($theme, $resolvers: $resolvers);
  $theme: keys.create-theme-properties(
    $theme,
    $prefix: $_custom-property-prefix
  );

  @include _container-shape(map.get($theme, container-shape));
  .mdc-evolution-chip__icon--primary {
    @include shape.radius(map.get($theme, with-avatar-avatar-shape));
  }
  @include graphic-size(map.get($theme, with-avatar-avatar-size));
  @include height(map.get($theme, container-height));
  @include elevation-theme.overlay-container-color(
    map.get($theme, container-surface-tint-layer-color)
  );
  @include _container-elevation(
    $map: (
      default: map.get($theme, container-elevation),
    )
  );
  @include _container-elevation(
    $map: (
      enabled: map.get($theme, flat-container-elevation),
    )
  );
  @include _container-elevation(
    $map: (
      enabled: map.get($theme, elevated-container-elevation),
      disabled: map.get($theme, elevated-disabled-container-elevation),
      hover: map.get($theme, elevated-hover-container-elevation),
      focus: map.get($theme, elevated-focus-container-elevation),
      pressed: map.get($theme, elevated-pressed-container-elevation),
    )
  );
  &.mdc-evolution-chip--selected {
    @include _container-elevation(
      (
        enabled: map.get($theme, elevated-selected-container-elevation),
        disabled:
          map.get($theme, elevated-selected-disabled-container-elevation),
        hover: map.get($theme, elevated-selected-hover-container-elevation),
        focus: map.get($theme, elevated-selected-focus-container-elevation),
        pressed: map.get($theme, elevated-selected-pressed-container-elevation),
      )
    );
    @include _container-elevation(
      (
        enabled: map.get($theme, flat-selected-container-elevation),
        disabled: map.get($theme, flat-selected-disabled-container-elevation),
        hover: map.get($theme, flat-selected-hover-container-elevation),
        focus: map.get($theme, flat-selected-focus-container-elevation),
        pressed: map.get($theme, flat-selected-pressed-container-elevation),
      )
    );
  }
  &:not(.mdc-evolution-chip--selected) {
    @include _container-elevation(
      (
        enabled: map.get($theme, flat-unselected-container-elevation),
        disabled: map.get($theme, flat-unselected-disabled-container-elevation),
        hover: map.get($theme, flat-unselected-hover-container-elevation),
        focus: map.get($theme, flat-unselected-focus-container-elevation),
        pressed: map.get($theme, flat-unselected-pressed-container-elevation),
      )
    );
  }
  @include outline-color(
    (
      enabled: map.get($theme, outline-color),
      focus: map.get($theme, focus-outline-color),
      disabled: map.get($theme, disabled-outline-color),
    )
  );
  @include outline-color(
    (
      enabled: map.get($theme, flat-outline-color),
      focus: map.get($theme, flat-focus-outline-color),
      disabled: map.get($theme, flat-disabled-outline-color),
    )
  );
  @include selected-outline-color(
    (
      enabled: map.get($theme, flat-selected-outline-color),
      disabled: map.get($theme, flat-disabled-selected-outline-color),
    )
  );
  &:not(.mdc-evolution-chip--selected) {
    @include outline-color(
      (
        disabled: map.get($theme, flat-disabled-unselected-outline-color),
        focus: map.get($theme, flat-unselected-focus-outline-color),
        enabled: map.get($theme, flat-unselected-outline-color),
      )
    );
  }
  @include outline-width(map.get($theme, outline-width));
  @include outline-width(map.get($theme, flat-outline-width));
  &.mdc-evolution-chip--selected {
    @include outline-width(map.get($theme, flat-selected-outline-width));
  }
  &:not(.mdc-evolution-chip--selected) {
    @include outline-width(map.get($theme, flat-unselected-outline-width));
  }
  @include container-color(
    (
      enabled: map.get($theme, elevated-container-color),
      disabled: map.get($theme, elevated-disabled-container-color),
    )
  );
  @include selected-container-color(
    (
      enabled: map.get($theme, elevated-selected-container-color),
      disabled: map.get($theme, elevated-disabled-container-color),
    )
  );
  // TODO(b/255716167) Separate theme-styles mixin for hairline and elevated chip variants.
  @include selected-container-color(
    (
      enabled: map.get($theme, flat-selected-container-color),
      disabled: map.get($theme, flat-disabled-selected-container-color),
    )
  );
  &:not(.mdc-evolution-chip--selected) {
    @include container-color(
      (
        enabled: map.get($theme, elevated-unselected-container-color),
      )
    );
  }
  .mdc-evolution-chip__text-label {
    @include typography.theme-styles(
      (
        font: map.get($theme, label-text-font),
        line-height: map.get($theme, label-text-line-height),
        size: map.get($theme, label-text-size),
        weight: map.get($theme, label-text-weight),
        tracking: map.get($theme, label-text-tracking),
      )
    );
  }
  @include text-label-color(
    (
      enabled: map.get($theme, label-text-color),
      hover: map.get($theme, hover-label-text-color),
      focus: map.get($theme, focus-label-text-color),
      pressed: map.get($theme, pressed-label-text-color),
      disabled: map.get($theme, disabled-label-text-color),
    )
  );
  @include selected-text-label-color(
    (
      enabled: map.get($theme, selected-label-text-color),
      hover: map.get($theme, selected-hover-label-text-color),
      focus: map.get($theme, selected-focus-label-text-color),
      pressed: map.get($theme, selected-pressed-label-text-color),
      disabled: map.get($theme, disabled-label-text-color),
    )
  );
  &:not(.mdc-evolution-chip--selected) {
    @include text-label-color(
      (
        enabled: map.get($theme, unselected-label-text-color),
        hover: map.get($theme, unselected-hover-label-text-color),
        focus: map.get($theme, unselected-focus-label-text-color),
        pressed: map.get($theme, unselected-pressed-label-text-color),
        disabled: map.get($theme, unselected-disabled-label-text-color),
      )
    );
  }

  @include icon-size(map.get($theme, with-icon-icon-size));
  @include icon-color(
    (
      enabled: map.get($theme, with-icon-icon-color),
      disabled: map.get($theme, with-icon-disabled-icon-color),
      hover: map.get($theme, with-icon-hover-icon-color),
      focus: map.get($theme, with-icon-focus-icon-color),
      pressed: map.get($theme, with-icon-pressed-icon-color),
    )
  );
  @include checkmark-color(
    (
      enabled: map.get($theme, with-icon-selected-icon-color),
      disabled: map.get($theme, with-icon-disabled-icon-color),
      hover: map.get($theme, with-icon-selected-hover-icon-color),
      focus: map.get($theme, with-icon-selected-focus-icon-color),
      pressed: map.get($theme, with-icon-selected-pressed-icon-color),
    )
  );
  &:not(.mdc-evolution-chip--selected) {
    @include icon-color(
      (
        enabled: map.get($theme, with-icon-unselected-icon-color),
        disabled: map.get($theme, with-icon-unselected-disabled-icon-color),
        hover: map.get($theme, with-icon-unselected-hover-icon-color),
        focus: map.get($theme, with-icon-unselected-focus-icon-color),
        pressed: map.get($theme, with-icon-unselected-pressed-icon-color),
      )
    );
  }
  @include icon-color(
    (
      disabled: map.get($theme, with-leading-icon-disabled-leading-icon-color),
      focus: map.get($theme, with-leading-icon-focus-leading-icon-color),
      hover: map.get($theme, with-leading-icon-hover-leading-icon-color),
      enabled: map.get($theme, with-leading-icon-leading-icon-color),
      pressed: map.get($theme, with-leading-icon-pressed-leading-icon-color),
    )
  );
  @include trailing-action-color(
    (
      disabled: map.get($theme, with-trailing-icon-disabled-trailing-icon-color),
      focus: map.get($theme, with-trailing-icon-focus-trailing-icon-color),
      hover: map.get($theme, with-trailing-icon-hover-trailing-icon-color),
      enabled: map.get($theme, with-trailing-icon-trailing-icon-color),
      pressed: map.get($theme, with-trailing-icon-pressed-trailing-icon-color),
    )
  );
  @include _ripple-theme(
    (
      focus-state-layer-color: map.get($theme, focus-state-layer-color),
      focus-state-layer-opacity: map.get($theme, focus-state-layer-opacity),
      hover-state-layer-color: map.get($theme, hover-state-layer-color),
      hover-state-layer-opacity: map.get($theme, hover-state-layer-opacity),
      pressed-state-layer-color: map.get($theme, pressed-state-layer-color),
      pressed-state-layer-opacity: map.get($theme, pressed-state-layer-opacity),
    )
  );
  &.mdc-evolution-chip--selected {
    @include _ripple-theme(
      (
        focus-state-layer-color:
          map.get($theme, selected-focus-state-layer-color),
        focus-state-layer-opacity:
          map.get($theme, selected-focus-state-layer-opacity),
        hover-state-layer-color:
          map.get($theme, selected-hover-state-layer-color),
        hover-state-layer-opacity:
          map.get($theme, selected-hover-state-layer-opacity),
        pressed-state-layer-color:
          map.get($theme, selected-pressed-state-layer-color),
        pressed-state-layer-opacity:
          map.get($theme, selected-pressed-state-layer-opacity),
      )
    );
  }
  &:not(.mdc-evolution-chip--selected) {
    @include _ripple-theme(
      (
        focus-state-layer-color:
          map.get($theme, unselected-focus-state-layer-color),
        focus-state-layer-opacity:
          map.get($theme, unselected-focus-state-layer-opacity),
        hover-state-layer-color:
          map.get($theme, unselected-hover-state-layer-color),
        hover-state-layer-opacity:
          map.get($theme, unselected-hover-state-layer-opacity),
        pressed-state-layer-color:
          map.get($theme, unselected-pressed-state-layer-color),
        pressed-state-layer-opacity:
          map.get($theme, unselected-pressed-state-layer-opacity),
      )
    );
  }
}

@function resolve-theme($theme, $resolvers) {
  $elevation-resolver: map.get($resolvers, elevation);
  @if $elevation-resolver == null {
    @return $theme;
  }

  $elevation-pairs: (
    container-shadow-color: (
      container-elevation,
    ),
    flat-container-shadow-color: (
      flat-container-elevation,
    ),
    elevated-container-shadow-color: (
      elevated-container-elevation,
      elevated-disabled-container-elevation,
      elevated-focus-container-elevation,
      elevated-hover-container-elevation,
      elevated-pressed-container-elevation,
      elevated-selected-container-elevation,
      elevated-selected-disabled-container-elevation,
      elevated-selected-focus-container-elevation,
      elevated-selected-hover-container-elevation,
      elevated-selected-pressed-container-elevation,
      flat-selected-focus-container-elevation,
      flat-selected-hover-container-elevation,
      flat-selected-pressed-container-elevation,
      flat-unselected-focus-container-elevation,
      flat-unselected-hover-container-elevation,
      flat-unselected-pressed-container-elevation,
    ),
  );

  @each $shadow-color-key, $elevation-keys in $elevation-pairs {
    $shadow-color: map.get($theme, $shadow-color-key);
    @if $shadow-color != null {
      @each $key in $elevation-keys {
        $elevation: map.get($theme, $key);
        @if $elevation != null {
          $resolved-value: meta.call(
            $elevation-resolver,
            $elevation: $elevation,
            $shadow-color: $shadow-color
          );
          // Update the key with the resolved value.
          $theme: map.set($theme, $key, $resolved-value);
        }
      }
    }
  }
  @return $theme;
}

@mixin _ripple-theme($ripple-theme) {
  .mdc-evolution-chip__action--primary {
    @include ripple-theme.internal-theme-styles(
      (
        focus-state-layer-color: map.get($ripple-theme, focus-state-layer-color),
        focus-state-layer-opacity:
          map.get($ripple-theme, focus-state-layer-opacity),
        hover-state-layer-color: map.get($ripple-theme, hover-state-layer-color),
        hover-state-layer-opacity:
          map.get($ripple-theme, hover-state-layer-opacity),
        pressed-state-layer-color:
          map.get($ripple-theme, pressed-state-layer-color),
        pressed-state-layer-opacity:
          map.get($ripple-theme, pressed-state-layer-opacity),
      ),
      $ripple-target: $ripple-target
    );
  }
}

///
/// Sets the ripple color of the chip.
/// @param {Color} $color - The color of the ripple.
/// @param {Map} $opacity-map [null] - The optional opacity map for the states.
///
@mixin ripple-color(
  $color,
  $opacity-map: null,
  $query: feature-targeting.all()
) {
  @include _ripple-color($color, $opacity-map, $query);
}

///
/// Sets the selected ripple color of the chip.
/// @param {Color} $color - The color of the ripple.
/// @param {Map} $opacity-map [null] - The optional opacity map for the states.
///
@mixin selected-ripple-color(
  $color,
  $opacity-map: null,
  $query: feature-targeting.all()
) {
  &.mdc-evolution-chip--selected {
    @include ripple-color($color, $opacity-map, $query: $query);
  }
}

@mixin _ripple-color($color, $opacity-map, $query) {
  .mdc-evolution-chip__action--primary {
    @include ripple-theme.states(
      $color: $color,
      $opacity-map: $opacity-map,
      $query: $query,
      $ripple-target: $ripple-target
    );
  }
}

///
/// Sets the ripple color of the chip's trailing action.
/// @param {Color} $color - The color of the ripple.
/// @param {Map} $opacity-map [null] - The optional opacity map for the states.
///
@mixin trailing-action-ripple-color(
  $color,
  $opacity-map: null,
  $query: feature-targeting.all()
) {
  .mdc-evolution-chip__action--trailing {
    @include ripple-theme.states(
      $color: $color,
      $opacity-map: $opacity-map,
      $query: $query,
      $ripple-target: $ripple-target
    );
  }
}

///
/// Sets the size of the trailing action's ripple.
/// @param {Number} $size - The size of the ripple.
///
@mixin trailing-action-ripple-size($size, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);
  .mdc-evolution-chip__ripple--trailing {
    @include feature-targeting.targets($feat-structure) {
      @include theme.property(height, $size);
      @include theme.property(width, $size);
    }
  }
}

///
/// Sets the density scale for the chip.
/// @param {Number | String} $density-scale - Density scale value for component.
///     Supported density scale values are `-2`, `-1`, `0`.
///
@mixin density($density-scale, $query: feature-targeting.all()) {
  $height: density.prop-value(
    $density-config: $density-config,
    $density-scale: $density-scale,
    $property-name: height,
  );

  @include height($height, $query: $query);

  @if $density-scale != 0 {
    @include _reset-touch-target($query: $query);
  }
}

///
/// Resets touch target-related styles. This is called from the density mixin to
/// automatically remove the increased touch target, since dense components
/// don't have the same default a11y requirements.
/// @access private
///
@mixin _reset-touch-target($query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-evolution-chip__action-touch {
    @include feature-targeting.targets($feat-structure) {
      display: none;
    }
  }
}

///
/// Sets custom height for the chip.
/// @param {Number} $height - The height of the chip.
///
@mixin height($height, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  @include feature-targeting.targets($feat-structure) {
    @include theme.property(height, $height);
  }
}

@mixin _container-shape($radius) {
  @include shape.radius($radius);

  #{$ripple-target} {
    @include shape.radius($radius);
  }

  .mdc-evolution-chip__action--primary:before {
    @include shape.radius($radius);
  }
}

///
/// Sets the shape radius of the chip.
/// @param {Number|List} $radius - Shape radius in `border-radius` CSS format.
/// @param {Boolean} $rtl-reflexive - True flips radius corners in RTL.
///
@mixin shape-radius(
  $radius,
  $rtl-reflexive: false,
  $density-scale: $density-scale,
  $query: feature-targeting.all()
) {
  $height: density.prop-value(
    $density-config: $density-config,
    $density-scale: $density-scale,
    $property-name: height,
  );

  @include shape.radius(
    $radius,
    $rtl-reflexive,
    $component-height: $height,
    $query: $query
  );

  #{$ripple-target} {
    @include shape.radius(
      $radius,
      $rtl-reflexive,
      $component-height: $height,
      $query: $query
    );
  }

  .mdc-evolution-chip__action--primary:before {
    @include shape.radius(
      $radius,
      $rtl-reflexive,
      $component-height: $height,
      $query: $query
    );
  }

  .mdc-evolution-chip__icon--primary {
    @include shape.radius(
      $radius,
      $rtl-reflexive,
      $component-height: $height,
      $query: $query
    );
  }
}

///
/// Sets the width of the chip outline.
/// @param {Number} $width - The width of the chip outline.
///
@mixin outline-width($width, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-evolution-chip__action--primary:before {
    @include feature-targeting.targets($feat-structure) {
      @include theme.property(border-width, $width);
    }
  }
}

///
/// Customizes the outline color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `enabled`, `focus`, `disabled`.
///
/// @example
///   @include outline-color(blue);
///   @include outline-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The outline's color or a state Map
///
@mixin outline-color($color-or-map, $query: feature-targeting.all()) {
  @include _outline-color(state.get-default-state($color-or-map), $query);
  &:not(.mdc-evolution-chip--disabled) {
    @include _outline-color(state.get-enabled-state($color-or-map), $query);
  }
  @include _focus-outline-color(state.get-focus-state($color-or-map), $query);
  &.mdc-evolution-chip--disabled {
    @include _outline-color(state.get-disabled-state($color-or-map), $query);
  }
}

///
/// Customizes the selected outline color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `enabled`, `focus`, `disabled`.
///
/// @example
///   @include selected-outline-color(blue);
///   @include selected-outline-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The outline's color or a state Map
///
@mixin selected-outline-color($color-or-map, $query: feature-targeting.all()) {
  &.mdc-evolution-chip--selected {
    @include outline-color($color-or-map, $query: $query);
  }
}

@mixin _outline-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__action--primary:before {
    @include feature-targeting.targets($feat-color) {
      @if $color {
        @include theme.property(border-color, $color);
      }

      // TODO(b/206694742): Find a better solution.
      @if $color == transparent {
        @include dom.forced-colors-mode($exclude-ie11: true) {
          @include theme.property(border-color, CanvasText);
        }
      }
    }
  }
}

@mixin _focus-outline-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational) {
    @include ripple-theme.focus() {
      &:before {
        @include feature-targeting.targets($feat-color) {
          @if $color {
            @include theme.property(border-color, $color);
          }
        }
      }
    }
  }
}

///
/// Sets the style of the chip outline.
/// @param {String} $style - The style of the chip outline.
///
@mixin outline-style($style, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-evolution-chip__action--primary:before {
    @include feature-targeting.targets($feat-structure) {
      @include theme.property(border-style, $style);
    }
  }
}

///
/// Customizes the container color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `enabled`, `disabled`.
///
/// @example
///   @include container-color(blue);
///   @include container-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The container's color or a state Map
///
@mixin container-color($color-or-map, $query: feature-targeting.all()) {
  @include _container-color(state.get-default-state($color-or-map), $query);
  &:not(.mdc-evolution-chip--disabled) {
    @include _container-color(state.get-enabled-state($color-or-map), $query);
  }
  &.mdc-evolution-chip--disabled {
    @include _container-color(state.get-disabled-state($color-or-map), $query);
  }
}

///
/// Customizes the selected container color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `enabled`, `disabled`.
///
/// @example
///   @include selected-container-color(blue);
///   @include selected-container-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The container's color or a state Map
///
@mixin selected-container-color(
  $color-or-map,
  $query: feature-targeting.all()
) {
  &.mdc-evolution-chip--selected {
    @include container-color($color-or-map, $query: $query);
  }
}

@mixin _container-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  @include feature-targeting.targets($feat-color) {
    @if $color {
      @include theme.property(background-color, $color);
    }
  }
}

///
/// Customizes the text label color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `enabled`, `hover`, `focus`, `disabled`.
///
/// @example
///   @include text-label-color(blue);
///   @include text-label-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The label's color or a state Map
///
@mixin text-label-color($color-or-map, $query: feature-targeting.all()) {
  @include _text-label-color(state.get-default-state($color-or-map), $query);
  &:not(.mdc-evolution-chip--disabled) {
    @include _text-label-color(state.get-enabled-state($color-or-map), $query);
  }
  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational):hover {
    @include _text-label-color(state.get-hover-state($color-or-map), $query);
  }

  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational) {
    @include ripple-theme.focus() {
      @include _text-label-color(state.get-focus-state($color-or-map), $query);
    }
  }

  &.mdc-evolution-chip--disabled {
    @include _text-label-color(state.get-disabled-state($color-or-map), $query);
  }
}

///
/// Customizes the selected text label color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `hover`, `focus`, `disabled`.
///
/// @example
///   @include selected-text-label-color(blue);
///   @include selected-text-label-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The label's color or a state Map
///
@mixin selected-text-label-color(
  $color-or-map,
  $query: feature-targeting.all()
) {
  &.mdc-evolution-chip--selected {
    @include text-label-color($color-or-map, $query: $query);
  }
}

@mixin _text-label-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__text-label {
    @include feature-targeting.targets($feat-color) {
      @if $color {
        @include theme.property(color, $color);
      }
    }
  }
}

///
/// Sets the type scale of the text label.
/// @param {String} $type-scale - The type scale of the text label.
///
@mixin text-label-type-scale($type-scale, $query: feature-targeting.all()) {
  .mdc-evolution-chip__text-label {
    @include typography.typography($type-scale, $query: $query);
  }
}

///
/// Sets the size of the graphic.
/// @param {Number} $size - The size of the graphic.
///
@mixin graphic-size($size, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  // Expose the width as a readable custom property that can be used when
  // computing the chip bounding client rect as an additive value for the chip
  // width. This solves for selectable chips without icons growing/shrinking as
  // they toggle their selected state. The ripple dimensions will have been
  // computed based on the unselected bounding client react which will not have
  // enough horizontal space to account for the growth in width.
  &.mdc-evolution-chip--selectable:not(.mdc-evolution-chip--with-primary-icon) {
    @if $size {
      @include theme.property(--mdc-chip-graphic-selected-width, $size);
    }
  }

  .mdc-evolution-chip__graphic {
    @include feature-targeting.targets($feat-structure) {
      @include theme.property(height, $size);
      @include theme.property(width, $size);
      @include theme.property(font-size, $size);
    }
  }
}

///
/// Customizes the icon color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `enabled`, `focus`, `disabled`.
///
/// @example
///   @include icon-color(blue);
///   @include icon-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The icon's color or a state Map
///
@mixin icon-color($color-or-map, $query: feature-targeting.all()) {
  @include _icon-color(state.get-default-state($color-or-map), $query);

  &:not(.mdc-evolution-chip--disabled) {
    @include _icon-color(state.get-enabled-state($color-or-map), $query);
  }

  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational):hover {
    @include _icon-color(state.get-hover-state($color-or-map), $query);
  }

  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational) {
    @include ripple-theme.focus() {
      @include _icon-color(state.get-focus-state($color-or-map), $query);
    }
  }

  &.mdc-evolution-chip--disabled {
    @include _icon-color(state.get-disabled-state($color-or-map), $query);
  }
}

@mixin _icon-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__icon--primary {
    @include feature-targeting.targets($feat-color) {
      @if $color {
        @include theme.property(color, $color);
      }
    }
  }
}

///
/// Customizes the icon container color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `hover`, `focus`, `disabled`.
///
/// @example
///   @include icon-container-color(blue);
///   @include icon-container-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The icon's container color or a state Map
///
@mixin icon-container-color($color-or-map, $query: feature-targeting.all()) {
  @include _icon-container-color(
    state.get-default-state($color-or-map),
    $query
  );

  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational):hover {
    @include _icon-container-color(
      state.get-hover-state($color-or-map),
      $query
    );
  }

  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational) {
    @include ripple-theme.focus() {
      @include _icon-container-color(
        state.get-focus-state($color-or-map),
        $query
      );
    }
  }

  &.mdc-evolution-chip--disabled {
    @include _icon-container-color(
      state.get-disabled-state($color-or-map),
      $query
    );
  }
}

@mixin _icon-container-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__icon--primary {
    @include feature-targeting.targets($feat-color) {
      @if $color {
        @include theme.property(background-color, $color);
      }
    }
  }
}

///
/// Sets the size of the icon.
/// @param {Number} $size - The size of the icon.
///
@mixin icon-size($size, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-evolution-chip__icon--primary {
    @include feature-targeting.targets($feat-structure) {
      @include theme.property(height, $size);
      @include theme.property(width, $size);
      @include theme.property(font-size, $size);
    }
  }
}

///
/// Sets the size of the trailing action.
/// @param {Number} $size - The size of the trailing action.
///
@mixin trailing-action-size($size, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-evolution-chip__icon--trailing {
    @include feature-targeting.targets($feat-structure) {
      @include theme.property(height, $size);
      @include theme.property(width, $size);
      @include theme.property(font-size, $size);
    }
  }
}

///
/// Customizes the trailing action color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `hover`, `focus`, `disabled`.
///
/// @example
///   @include trailing-action-color(blue);
///   @include trailing-action-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The trailing action's color or a state Map
///
@mixin trailing-action-color($color-or-map, $query: feature-targeting.all()) {
  @include _trailing-action-color(
    state.get-default-state($color-or-map),
    $query
  );

  &:not(.mdc-evolution-chip--disabled) {
    @include _trailing-action-color(
      state.get-enabled-state($color-or-map),
      $query
    );
  }

  .mdc-evolution-chip__action--trailing:hover {
    @include _trailing-action-color(
      state.get-hover-state($color-or-map),
      $query
    );
  }

  .mdc-evolution-chip__action--trailing {
    @include ripple-theme.focus() {
      @include _trailing-action-color(
        state.get-focus-state($color-or-map),
        $query
      );
    }
  }

  &.mdc-evolution-chip--disabled {
    @include _trailing-action-color(
      state.get-disabled-state($color-or-map),
      $query
    );
  }
}

@mixin _trailing-action-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__icon--trailing {
    @include feature-targeting.targets($feat-color) {
      @if $color {
        @include theme.property(color, $color);
      }
    }
  }
}

///
/// Sets the size of the checkmark.
/// @param {Number} $size - The size of the checkmark.
///
@mixin checkmark-size($size, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-evolution-chip__checkmark {
    @include feature-targeting.targets($feat-structure) {
      @include theme.property(height, $size);
      @include theme.property(width, $size);
    }
  }
}

///
/// Customizes the checkmark color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `enabled`, `hover`, `focus`, `disabled`.
///
/// @example
///   @include checkmark-color(blue);
///   @include checkmark-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The checkmark's color or a state Map
///
@mixin checkmark-color($color-or-map, $query: feature-targeting.all()) {
  @include _checkmark-color(state.get-default-state($color-or-map), $query);

  &:not(.mdc-evolution-chip--disabled) {
    @include _checkmark-color(state.get-enabled-state($color-or-map), $query);
  }

  .mdc-evolution-chip__action--primary:not(.mdc-evolution-chip__action--presentational):hover {
    @include _checkmark-color(state.get-hover-state($color-or-map), $query);
  }

  .mdc-evolution-chip__action--primary {
    @include ripple-theme.focus() {
      @include _checkmark-color(state.get-focus-state($color-or-map), $query);
    }
  }

  &.mdc-evolution-chip--disabled {
    @include _checkmark-color(state.get-disabled-state($color-or-map), $query);
  }
}

@mixin _checkmark-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__checkmark {
    @include feature-targeting.targets($feat-color) {
      @if $color {
        @include theme.property(color, $color);
      }
    }
  }
}

///
/// Customizes the checkmark container color, using a Color or state Map.
/// - To set only the default color, provide a single Color.
/// - To set one or more state colors, provide a state Map with optional keys.
/// - Supported state Map keys: `default`, `hover`, `focus`, `disabled`.
///
/// @example
///   @include checkmark-container-color(blue);
///   @include checkmark-container-color((disabled: gray));
///
/// @param {Color | Map} $color-or-map - The checkmark container's color or a state Map
///
@mixin checkmark-container-color(
  $color-or-map,
  $query: feature-targeting.all()
) {
  @include _checkmark-container-color(
    state.get-default-state($color-or-map),
    $query
  );

  &.mdc-evolution-chip--disabled {
    @include _checkmark-container-color(
      state.get-disabled-state($color-or-map),
      $query
    );
  }
}

@mixin _checkmark-container-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-evolution-chip__checkmark-background {
    @include feature-targeting.targets($feat-color) {
      @if $color {
        @include theme.property(background-color, $color);
      }
    }
  }
}

///
/// Sets the horizontal padding for the chip.
/// @param {Number} $leading - The leading padding for the chip.
/// @param {Number} $trailing [$leading] - The trailing padding for the chip.
///
@mixin horizontal-padding(
  $leading,
  $trailing: $leading,
  $query: feature-targeting.all()
) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-evolution-chip__action--primary {
    @include feature-targeting.targets($feat-structure) {
      @include rtl.reflexive-property(padding, $leading, $trailing);
    }
  }
}

///
/// Sets the horizontal padding for chips with a graphic.
/// @param {Number} $graphic-leading - The leading padding for the graphic.
/// @param {Number} $graphic-trailing - The trailing padding for the graphic.
/// @param {Number} $primary-trailing - The trailing padding for the primary action.
///
@mixin with-graphic-horizontal-padding(
  $graphic-leading,
  $graphic-trailing,
  $primary-trailing,
  $query: feature-targeting.all()
) {
  $feat-structure: feature-targeting.create-target($query, structure);

  &.mdc-evolution-chip--with-primary-graphic {
    .mdc-evolution-chip__graphic {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-property(
          padding,
          $graphic-leading,
          $graphic-trailing
        );
      }
    }

    .mdc-evolution-chip__action--primary {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-property(padding, 0, $primary-trailing);
      }
    }
  }
}

///
/// Sets the horizontal padding for chips with a trailing action.
/// @param {Number} $primary-leading - The leading padding for the primary action.
/// @param {Number} $trailing-action-leading - The leading padding for the trailing action.
/// @param {Number} $trailing-action-trailing - The trailing padding for the trailing action.
///
@mixin with-trailing-action-horizontal-padding(
  $primary-leading,
  $trailing-action-leading,
  $trailing-action-trailing,
  $query: feature-targeting.all()
) {
  $feat-structure: feature-targeting.create-target($query, structure);

  &.mdc-evolution-chip--with-trailing-action {
    .mdc-evolution-chip__action--trailing {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-property(
          padding,
          $trailing-action-leading,
          $trailing-action-trailing
        );
      }
    }

    #{$ripple-target-trailing} {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-position(left, $trailing-action-leading);
      }
    }

    .mdc-evolution-chip__action--primary {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-property(padding, $primary-leading, 0);
      }
    }
  }
}

///
/// Sets the horizontal padding for chips with a graphic and trailing action.
/// @param {Number} $graphic-leading - The leading padding for the graphic.
/// @param {Number} $graphic-trailing - The trailing padding for the graphic.
/// @param {Number} $trailing-action-leading - The leading padding for the trailing action.
/// @param {Number} $trailing-action-trailing - The trailing padding for the trailing action.
///
@mixin with-graphic-and-trailing-action-horizontal-padding(
  $graphic-leading,
  $graphic-trailing,
  $trailing-action-leading,
  $trailing-action-trailing,
  $query: feature-targeting.all()
) {
  $feat-structure: feature-targeting.create-target($query, structure);
  &.mdc-evolution-chip--with-primary-graphic.mdc-evolution-chip--with-trailing-action {
    .mdc-evolution-chip__graphic {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-property(
          padding,
          $graphic-leading,
          $graphic-trailing
        );
      }
    }

    .mdc-evolution-chip__action--trailing {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-property(
          padding,
          $trailing-action-leading,
          $trailing-action-trailing
        );
      }
    }

    #{$ripple-target-trailing} {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-position(left, $trailing-action-leading);
      }
    }

    .mdc-evolution-chip__action--primary {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-property(padding, 0, 0);
      }
    }
  }
}

@mixin _container-elevation-theme($theme) {
  @if map.get($theme, shadow) {
    @include elevation-theme.shadow(map.get($theme, shadow));
  }
  @if map.get($theme, overlay-opacity) {
    @include elevation-theme.overlay-opacity(map.get($theme, overlay-opacity));
  }
  // TODO(b/260053182): Remove setting overlay color after migration of customers
  @if map.get($theme, overlay-color) {
    @include elevation-theme.overlay-container-color(
      map.get($theme, overlay-color)
    );
  }
}

// TODO(b/259913622): Use elevation's theme-style() mixin.
@mixin _container-elevation($map) {
  $default-state: state.get-default-state($map);
  @if $default-state {
    @include _container-elevation-theme($default-state);
  }

  &:not(.mdc-evolution-chip--disabled) {
    $enabled-state: state.get-enabled-state($map);
    @if $enabled-state {
      @include _container-elevation-theme($enabled-state);
    }
  }

  @include ripple-theme.hover() {
    $hover-state: state.get-hover-state($map);
    @if $hover-state {
      @include _container-elevation-theme($hover-state);
    }
  }

  @include ripple-theme.focus() {
    $focus-state: state.get-focus-state($map);
    @if $focus-state {
      @include _container-elevation-theme($focus-state);
    }
  }

  @include ripple-theme.pressed() {
    $pressed-state: state.get-pressed-state($map);
    @if $pressed-state {
      @include _container-elevation-theme($pressed-state);
    }
  }

  &.mdc-evolution-chip--disabled {
    $disabled-state: state.get-disabled-state($map);
    @if $disabled-state {
      @include _container-elevation-theme($disabled-state);
    }
  }
}

@mixin button-cursor($cursor) {
  .mdc-evolution-chip__action {
    cursor: $cursor;
  }
}
